// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {FittingType} from './constants.js';

// Handles events specific to the PDF viewer and logs the corresponding metrics.

/**
 * Records when the zoom mode is changed to fit a FittingType.
 * @param {FittingType} fittingType the new FittingType.
 */
export function recordFitTo(fittingType) {
  if (fittingType === FittingType.FIT_TO_PAGE) {
    record(UserAction.FIT_TO_PAGE);
  } else if (fittingType === FittingType.FIT_TO_WIDTH) {
    record(UserAction.FIT_TO_WIDTH);
  }
  // There is no user action to do a fit-to-height, this only happens with
  // the open param "view=FitV".
}

/**
 * Records the given action to chrome.metricsPrivate.
 * @param {UserAction} action
 */
export function record(action) {
  if (!chrome.metricsPrivate) {
    return;
  }
  if (!actionsMetric) {
    actionsMetric = {
      'metricName': 'PDF.Actions',
      'type': chrome.metricsPrivate.MetricTypeType.HISTOGRAM_LOG,
      'min': 1,
      'max': UserAction.NUMBER_OF_ACTIONS,
      'buckets': UserAction.NUMBER_OF_ACTIONS + 1
    };
  }
  chrome.metricsPrivate.recordValue(actionsMetric, action);
  if (firstMap.has(action)) {
    const firstAction = firstMap.get(action);
    if (!firstActionRecorded.has(firstAction)) {
      chrome.metricsPrivate.recordValue(actionsMetric, firstAction);
      firstActionRecorded.add(firstAction);
    }
  }
}

export function resetForTesting() {
  firstActionRecorded.clear();
  actionsMetric = null;
}

/** @type {?chrome.metricsPrivate.MetricType} */
let actionsMetric = null;

/** @type {!Set<!UserAction>} */
const firstActionRecorded = new Set();

// Keep in sync with enums.xml.
// Do not change the numeric values or reuse them since these numbers are
// persisted to logs.
/**
 * User Actions that can be recorded by calling record.
 * The *_FIRST values are recorded automaticlly,
 * eg. record(...ROTATE) will also record ROTATE_FIRST
 * on the first instance.
 * @enum {number}
 */
export const UserAction = {
  // Recorded when the document is first loaded. This event serves as
  // denominator to determine percentages of documents in which an action was
  // taken as well as average number of each action per document.
  DOCUMENT_OPENED: 0,

  // Recorded when the document is rotated clockwise or counter-clockwise.
  ROTATE_FIRST: 1,
  ROTATE: 2,

  FIT_TO_WIDTH_FIRST: 3,
  FIT_TO_WIDTH: 4,

  FIT_TO_PAGE_FIRST: 5,
  FIT_TO_PAGE: 6,

  // Recorded when a bookmark is followed.
  FOLLOW_BOOKMARK_FIRST: 9,
  FOLLOW_BOOKMARK: 10,

  // Recorded when the page selection is used to navigate to another page.
  PAGE_SELECTOR_NAVIGATE_FIRST: 11,
  PAGE_SELECTOR_NAVIGATE: 12,

  // Recorded when the user triggers a save of the document.
  SAVE_FIRST: 13,
  SAVE: 14,

  // Recorded when the user triggers a save of the document and the document
  // has been modified by annotations.
  SAVE_WITH_ANNOTATION_FIRST: 15,
  SAVE_WITH_ANNOTATION: 16,

  PRINT_FIRST: 17,
  PRINT: 18,

  ENTER_ANNOTATION_MODE_FIRST: 19,
  ENTER_ANNOTATION_MODE: 20,

  EXIT_ANNOTATION_MODE_FIRST: 21,
  EXIT_ANNOTATION_MODE: 22,

  // Recorded when a pen stroke is made.
  ANNOTATE_STROKE_TOOL_PEN_FIRST: 23,
  ANNOTATE_STROKE_TOOL_PEN: 24,

  // Recorded when an eraser stroke is made.
  ANNOTATE_STROKE_TOOL_ERASER_FIRST: 25,
  ANNOTATE_STROKE_TOOL_ERASER: 26,

  // Recorded when a highlighter stroke is made.
  ANNOTATE_STROKE_TOOL_HIGHLIGHTER_FIRST: 27,
  ANNOTATE_STROKE_TOOL_HIGHLIGHTER: 28,

  // Recorded when a stroke is made using touch.
  ANNOTATE_STROKE_DEVICE_TOUCH_FIRST: 29,
  ANNOTATE_STROKE_DEVICE_TOUCH: 30,

  // Recorded when a stroke is made using mouse.
  ANNOTATE_STROKE_DEVICE_MOUSE_FIRST: 31,
  ANNOTATE_STROKE_DEVICE_MOUSE: 32,

  // Recorded when a stroke is made using pen.
  ANNOTATE_STROKE_DEVICE_PEN_FIRST: 33,
  ANNOTATE_STROKE_DEVICE_PEN: 34,

  // Recorded when two-up view mode is enabled.
  TWO_UP_VIEW_ENABLE_FIRST: 35,
  TWO_UP_VIEW_ENABLE: 36,

  // Recorded when two-up view mode is disabled.
  TWO_UP_VIEW_DISABLE_FIRST: 37,
  TWO_UP_VIEW_DISABLE: 38,

  // Recorded when zoom in button is clicked.
  ZOOM_IN_FIRST: 39,
  ZOOM_IN: 40,

  // Recorded when zoom out button is clicked.
  ZOOM_OUT_FIRST: 41,
  ZOOM_OUT: 42,

  // Recorded when the custom zoom input field is modified.
  ZOOM_CUSTOM_FIRST: 43,
  ZOOM_CUSTOM: 44,

  // Recorded when a thumbnail is used for navigation.
  THUMBNAIL_NAVIGATE_FIRST: 45,
  THUMBNAIL_NAVIGATE: 46,

  // Recorded when the user triggers a save of the document and the document
  // has never been modified.
  SAVE_ORIGINAL_ONLY_FIRST: 47,
  SAVE_ORIGINAL_ONLY: 48,

  // Recorded when the user triggers a save of the original document, even
  // though the document has been modified.
  SAVE_ORIGINAL_FIRST: 49,
  SAVE_ORIGINAL: 50,

  // Recorded when the user triggers a save of the edited document.
  SAVE_EDITED_FIRST: 51,
  SAVE_EDITED: 52,

  // Recorded when the sidenav menu button is clicked.
  TOGGLE_SIDENAV_FIRST: 53,
  TOGGLE_SIDENAV: 54,

  // Recorded when the thumbnails button in the sidenav is clicked.
  SELECT_SIDENAV_THUMBNAILS_FIRST: 55,
  SELECT_SIDENAV_THUMBNAILS: 56,

  // Recorded when the outline button in the sidenav is clicked.
  SELECT_SIDENAV_OUTLINE_FIRST: 57,
  SELECT_SIDENAV_OUTLINE: 58,

  // Recorded when the show/hide annotations overflow menu item is clicked.
  TOGGLE_DISPLAY_ANNOTATIONS_FIRST: 59,
  TOGGLE_DISPLAY_ANNOTATIONS: 60,

  // Recorded when the present menu item is clicked.
  PRESENT_FIRST: 61,
  PRESENT: 62,

  // Recorded when the document properties menu item is clicked.
  PROPERTIES_FIRST: 63,
  PROPERTIES: 64,

  NUMBER_OF_ACTIONS: 65,
};

/** @return {!Map<!UserAction, !UserAction>} */
function createFirstMap() {
  const entries = Object.entries(UserAction).sort((a, b) => a[1] - b[1]);
  // Exclude the first and last entries (DOCUMENT_OPENED, and NUMBER_OF_ACTIONS)
  // which don't have an equivalent "_FIRST" UserAction.
  const entriesWithFirst = entries.slice(1, entries.length - 1);
  const map = new Map();
  for (let i = 0; i < entriesWithFirst.length; i += 2) {
    map.set(entriesWithFirst[i + 1][1], entriesWithFirst[i][1]);
  }
  return map;
}

// Map from UserAction to the 'FIRST' action. These metrics are recorded
// by PDFMetrics.log the first time each corresponding action occurs.
/** @type {!Map<!UserAction, !UserAction>} */
const firstMap = createFirstMap();
